// Copyright Epic Games, Inc. All Rights Reserved.


#include "SMyComboButton.h"

#include "ListLibrary/ListUIStyle.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Input/SButton.h"
#include "Framework/Application/SlateApplication.h"
#include "ListLibrary/GlobalConfig.h"
#include "Widgets/Colors/SColorBlock.h"


void SMyComboButton::Construct( const FArguments& InArgs )
{
	check(InArgs._ComboButtonStyle);

	// Work out which values we should use based on whether we were given an override, or should use the style's version
	const FButtonStyle* const OurButtonStyle = InArgs._ButtonStyle ? InArgs._ButtonStyle : &InArgs._ComboButtonStyle->ButtonStyle;

	MenuBorderBrush = &InArgs._ComboButtonStyle->MenuBorderBrush;
	MenuBorderPadding = InArgs._ComboButtonStyle->MenuBorderPadding;
	
	OnComboBoxOpened = InArgs._OnComboBoxOpened;
	ContentWidgetPtr = InArgs._MenuContent.Widget;
	bIsFocusable = InArgs._IsFocusable;
	OnHovered = InArgs._OnHovered;
	OnUnhovered = InArgs._OnUnhovered;
	OnOpenMenu = InArgs._OnOpenMenu;
	const bool bHasDownArrowShadow = !InArgs._ComboButtonStyle->ShadowOffset.IsZero();

	TSharedPtr<SHorizontalBox> HBox;

	SMenuAnchor::Construct( SMenuAnchor::FArguments()
		.Placement(InArgs._MenuPlacement)
		.Method(InArgs._Method)
		.OnMenuOpenChanged(InArgs._OnMenuOpenChanged)
		.OnGetMenuContent(InArgs._OnGetMenuContent)
		.IsCollapsedByParent(InArgs._CollapseMenuOnParentFocus)
		[
			SNew( SButton )
			.ButtonStyle(ListUIStyle::GetButtonStyle("FilletAngleButtonStyle")  )
			.OnClicked( this, &SMyComboButton::OnButtonClicked )
			/*[
				SNew(SColorBlock).Color(FLinearColor::Red)
			]*/
		]
	);

	
	// The menu that pops up when we press the button.
	// We keep this content around, and then put it into a new window when we need to pop
	// it up.
	SetMenuContent( InArgs._MenuContent.Widget );
}

FReply SMyComboButton::OnButtonClicked()
{
	if(OnOpenMenu.IsBound())
	{
		if(OnOpenMenu.Execute() == false)
			return FReply::Handled();
	}
	// Button was clicked; show the popup.
	// Do nothing if clicking on the button also dismissed the menu, because we will end up doing the same thing twice.
	// Don't explicitly focus the menu, here, we're going to do it in the button reply so that it's properly focused
	// to the correct user.
	SetIsOpen( ShouldOpenDueToClick(), false );

	// If the menu is open, execute the related delegate.
	if( IsOpen() && OnComboBoxOpened.IsBound() )
	{
		OnComboBoxOpened.Execute();
	}

	// Focusing any newly-created widgets must occur after they have been added to the UI root.
	FReply ButtonClickedReply = FReply::Handled();
	
	if (bIsFocusable)
	{
		TSharedPtr<SWidget> WidgetToFocus = WidgetToFocusPtr.Pin();
		if (!WidgetToFocus.IsValid())
		{
			// no explicitly focused widget, try to focus the content that is a child of the border
			if (WrappedContent.IsValid() && WrappedContent->GetChildren()->Num() == 1)
			{
				WidgetToFocus = WrappedContent->GetChildren()->GetChildAt(0);
			}
		}

		if (!WidgetToFocus.IsValid())
		{
			// no explicitly focused widget, try to focus the content
			WidgetToFocus = MenuContent;
		}

		if (!WidgetToFocus.IsValid())
		{
			// no content, so try to focus the original widget set on construction
			WidgetToFocus = ContentWidgetPtr.Pin();
		}

		if (WidgetToFocus.IsValid())
		{
			ButtonClickedReply.SetUserFocus(WidgetToFocus.ToSharedRef(), EFocusCause::SetDirectly);
		}
	}

	return ButtonClickedReply;
}

FReply SMyComboButton::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
{
	FReply Reply = FReply::Unhandled();
	if (FSlateApplication::Get().GetNavigationActionFromKey(InKeyEvent) == EUINavigationAction::Accept)
	{
		// Handle menu open with controller.
		Reply = OnButtonClicked();
	}

	return Reply;
}

void SMyComboButton::SetMenuContent(TSharedRef<SWidget> InContent)
{
	WrappedContent = MenuContent =
		SNew(SBorder)
		.BorderImage(MenuBorderBrush)
		.Padding(MenuBorderPadding)
		[
			InContent
		];
}

void SMyComboButton::SetOnGetMenuContent(FOnGetContent InOnGetMenuContent)
{
	OnGetMenuContent = InOnGetMenuContent;
}


void SMyComboButton::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	SMenuAnchor::OnMouseEnter(MyGeometry, MouseEvent);
	OnHovered.ExecuteIfBound();
}

void SMyComboButton::OnMouseLeave(const FPointerEvent& MouseEvent)
{
	SMenuAnchor::OnMouseLeave(MouseEvent);
	OnUnhovered.ExecuteIfBound();
}
